package com.example.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.util.Result;
import com.example.dto.system.MetaDto;
import com.example.dto.system.RouterDto;
import com.example.dto.system.SysMenuRoleDto;
import com.example.system.SysMenu;
import com.example.system.SysRoleMenu;
import com.example.system.helper.MenuHelper;
import com.example.system.mapper.SysMenuMapper;
import com.example.system.mapper.SysRoleMenuMapper;
import com.example.system.service.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    /**
     * 查询菜单列表
     * @return
     */
    public Result findNodes(){
        //1 查询所有菜单数据
        List<SysMenu> list = list();


        //2 构建树形结构
//        {
//            第一层
//            children:[
//            {
//                第二层
//                        ....
//            }
//            ]
//        }
        List<SysMenu> sysMenus = MenuHelper.buildTree(list);
        return Result.ok(sysMenus);
    }

    /**
     * 删除菜单
     * @param id
     * @return
     */
    @Override
    @Transactional
    public Result remove(Long id) {
//        1、查询该菜单下是否有子菜单
        LambdaQueryWrapper<SysMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysMenu::getParentId,id);
        List<SysMenu> list = list(wrapper);
//        System.out.println("list=="+list);
//        System.out.println("listsize=="+list.size());
        if(list.size() != 0){
            return Result.fail("该菜单不能删除");
        }
        LambdaQueryWrapper<SysMenu> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(SysMenu::getId,id);
        remove(wrapper1);
        return Result.ok();
    }

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    /**
     * 查询所有菜单和角色分配的菜单
     * @param roleId
     * @return
     */
    @Override
    public Result toAssign(Long roleId) {
        if(roleId == null){
            return Result.fail();
        }
//        1、查询所有菜单列表 status = 1
        LambdaQueryWrapper<SysMenu> sysMenuWrapper = new LambdaQueryWrapper<>();
        sysMenuWrapper.eq(SysMenu::getStatus,1);
        List<SysMenu> allMenu = list(sysMenuWrapper);

//        2、查询该角色下的菜单
        LambdaQueryWrapper<SysRoleMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRoleMenu::getRoleId,roleId);
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuMapper.selectList(wrapper);

//        3、获取该角色有的菜单id  collect 菜单的id集合
        List<Long> collect = sysRoleMenus.stream().map(c -> c.getMenuId()).collect(Collectors.toList());
//        System.out.println("collect=="+collect);

//        4、用流的方法来过滤该角色有的权限
        List<SysMenu> sysMenus = allMenu.stream().map(c -> {
            if (collect.contains(c.getId())) {
                c.setSelect(true);
                return c;
            }
            c.setSelect(false);
            return c;
        }).collect(Collectors.toList());
//        System.out.println("sysMenus=="+sysMenus);

//        List<SysMenu> list = new ArrayList<>();
//        for (SysMenu menu : allMenu) {
//            if(collect.contains(menu.getId())){
//                menu.setSelect(true);
//                list.add(menu);
//            }else {
//                menu.setSelect(false);
//                list.add(menu);
//            }
//        }
//        System.out.println("list=="+list);

        List<SysMenu> list1 = MenuHelper.buildTree(sysMenus);
        return Result.ok(list1);
    }

    /**
     * 为角色分配权限
     * @param sysMenuRoleDto
     * @return
     */
    @Override
    public Result doAssign(SysMenuRoleDto sysMenuRoleDto) {
        if(sysMenuRoleDto == null){
            return Result.fail();
        }

//        1、删除该角色的所有权限
        Long roleId = sysMenuRoleDto.getRoleId();
        LambdaQueryWrapper<SysRoleMenu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysRoleMenu::getRoleId, roleId);
        sysRoleMenuMapper.delete(wrapper);

//        2、为角色添加权限
        List<Long> idList = sysMenuRoleDto.getMenuIdList();
        idList.stream().forEach( c -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(c);
            sysRoleMenu.setRoleId(roleId);
            sysRoleMenuMapper.insert(sysRoleMenu);
        });

        return Result.ok();
    }

    @Autowired
    private SysMenuMapper sysMenuMapper;

    /**
     * 获取用户菜单
     * @param userId
     * @return
     */
    @Override
    public List<RouterDto> findUserMenuList(Long userId) {
        //超级管理员admin账号id为：1
        List<SysMenu> sysMenuList = null;
        if(userId == 1){
            sysMenuList = this.list(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getStatus,1).orderByAsc(SysMenu::getSortValue));
        }else {
            sysMenuList = sysMenuMapper.findListByUserId(userId);
        }

        //构建树形数据
        List<SysMenu> sysTreeMenus = MenuHelper.buildTree(sysMenuList);

        List<RouterDto> routerDtoList = this.buildMenus(sysTreeMenus);
        return routerDtoList;

    }

    /**
     * 根据菜单构建路由
     * @param menus
     * @return
     */
    private List<RouterDto> buildMenus(List<SysMenu> menus) {
        List<RouterDto> routers = new LinkedList<>();
        menus.stream().forEach( menu -> {
            RouterDto router = new RouterDto();
            router.setHidden(false);
            router.setAlwaysShow(false);
            router.setPath(getRouterPath(menu));
            router.setComponent(menu.getComponent());
            router.setMeta(new MetaDto(menu.getName(),menu.getIcon()));
            List<SysMenu> children = menu.getChildren();
            //如果当前是菜单，需将按钮对应的路由加载出来，如：“角色授权”按钮对应的路由在“系统管理”下面
            if(menu.getType().intValue() == 1){
                List<SysMenu> hiddenMenuList = children.stream()
                        .filter( item -> !StringUtils.isEmpty(item.getComponent())).collect(Collectors.toList());
                hiddenMenuList.stream().forEach( hiddenMenu -> {
                    RouterDto hiddenRouter = new RouterDto();
                    hiddenRouter.setHidden(true);
                    hiddenRouter.setAlwaysShow(false);
                    hiddenRouter.setPath(getRouterPath(hiddenMenu));
                    hiddenRouter.setComponent(hiddenMenu.getComponent());
                    hiddenRouter.setMeta(new MetaDto(hiddenMenu.getName(),hiddenMenu.getIcon()));
                    routers.add(hiddenRouter);
                });
            }else {
                if(!CollectionUtils.isEmpty(children)){
                    if (children.size() > 0){
                        router.setAlwaysShow(true);
                    }
                    router.setChildren(buildMenus(children));
                }
            }
            routers.add(router);
        });
//        System.out.println("routers=="+routers);
        return  routers;
    }

    /**
     * 获取路由地址
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(SysMenu menu) {
        String routerPath = "/" +menu.getPath();
        if(menu.getParentId().intValue() != 0){
            routerPath = menu.getPath();
        }
        return routerPath;
    }

    /**
     * 获取用户按钮权限
     * @param userId
     * @return
     */
    @Override
    public List<String> findUserPermsList(Long userId) {
        //超级管理员admin账号id为：1
        List<SysMenu> sysMenuList = null;
        if (userId.longValue() == 1){
            sysMenuList = this.list(Wrappers.<SysMenu>lambdaQuery().eq(SysMenu::getStatus,1));
        }else {
            sysMenuList = sysMenuMapper.findListByUserId(userId);
        }
        List<String> permsList = sysMenuList.stream()
                .filter( item -> item.getType() == 2)
                .map( itme -> itme.getPerms())
                .collect(Collectors.toList());
        return permsList;
    }
}
